package com.example.forestmanagement.ui.map;

import static android.content.Context.MODE_PRIVATE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.PopupMenu;
import android.widget.SearchView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.android.arouter.launcher.ARouter;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.android.volley.Request;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.example.forestapp.CommandCenterActivity;
import com.example.forestmanagement.HistoryDataActivity;
import com.example.forestmanagement.ProfileActivity;
import com.example.forestmanagement.R;
import com.example.forestmanagement.SettingsActivity;
import com.example.forestmanagement.TrackPlaybackActivity;
import com.example.forestmanagement.adapter.MarkListAdapter;
import com.example.forestmanagement.databinding.FragmentMapBinding;
import com.example.forestmanagement.db.LocationDBHelper;
import com.example.forestmanagement.model.LocationPoint;
import com.example.forestmanagement.model.MarkData;
import com.example.forestmanagement.model.User;
import com.example.forestmanagement.ui.login.LoginActivity;
import com.google.android.material.bottomsheet.BottomSheetDialog;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import io.openim.android.ouicore.base.BaseApp;
import io.openim.android.ouicore.base.BaseFragment;
import io.openim.android.ouicore.base.vm.injection.Easy;
import io.openim.android.ouicore.ex.MultipleChoice;
import io.openim.android.ouicore.im.IMUtil;
import io.openim.android.ouicore.utils.Routes;
import io.openim.android.ouicore.vm.GroupVM;
import io.openim.android.ouicore.vm.SelectTargetVM;
import io.openim.android.ouicore.widget.CommonDialog;
import io.openim.android.ouicore.widget.WaitDialog;
import io.openim.android.sdk.OpenIMClient;
import io.openim.android.sdk.enums.MessageStatus;
import io.openim.android.sdk.listener.OnBase;
import io.openim.android.sdk.listener.OnMsgSendCallback;
import io.openim.android.sdk.models.Message;
import io.openim.android.sdk.models.OfflinePushInfo;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;


public class MapFragment extends BaseFragment implements AMap.OnMapClickListener, AMap.OnMarkerClickListener, View.OnClickListener, AMapLocationListener {
    private FragmentMapBinding binding;
    private static final String TAG = "MapFragment";
    private static final String API_BASE_URL = "http://8.130.186.54:9898";
    private static final String API_UPDATE_LOCATION = API_BASE_URL + "/app-api/linban/user/update-user-alive";
    private static final String API_BATCH_UPDATE_LOCATION = API_BASE_URL + "/app-api/linban/user-track/batch-create";
    private static final String BASE_URL = "http://8.130.186.54:9898";
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");

    private User currentUser;
    private LocationDBHelper dbHelper;
    private boolean isNetworkAvailable = true;

    private MapView mapView;
    private AMap aMap;
    /// 声明mlocationClient对象
    public AMapLocationClient mlocationClient;
    //声明mLocationOption对象
    public AMapLocationClientOption mLocationOption = null;
    private BottomSheetDialog drawToolsDialog;
    private BottomSheetDialog markListDialog;

    // 地图相关
    private Map<Polygon, MarkData> polygonMarkMap = new HashMap<>();
    //


    // 绘制相关变量
    private int currentDrawMode = 0; // 0: 无, 1: 点, 2: 线, 3: 面
    private int currentColor = Color.parseColor("#4285F4");
    private float currentWidth = 3.0f;
    private List<LatLng> drawPoints = new ArrayList<>();
    private Marker currentMarker;
    private Polyline currentPolyline;
    private Polygon currentPolygon;
    private EditText etMarkName, etMarkDesc;

    // 标注列表相关
    private List<MarkData> markList = new ArrayList<>();
    private LinkedHashMap<Integer,Marker> userMarkers =new LinkedHashMap<>();

    private List<Marker> labelMarkers = new ArrayList<>();
    private LinkedHashMap<Integer ,Marker> labelMarkerMap = new LinkedHashMap<>();

    private List<Polyline> loadedPolylines = new ArrayList<>();
    private List<Polygon> loadedPolygons = new ArrayList<>();
    private MarkListAdapter markListAdapter;

    Bitmap originalIcon = null;
    Bitmap userOriginIcon = null;
    Bitmap scaledIcon = null; // 40x40像素
    Bitmap userMarker = null;

    int targetWidth = 50;
    int targetHeight = 50;

    boolean dev = false;

    private OkHttpClient client = new OkHttpClient();
    private int userId = -1; // TODO: 从登录信息获取

    // 添加标注点ID映射
    private Map<String, MarkData> markerMap = new HashMap<>();

    private List<Marker> tempMarkers = new ArrayList<>();
    private Marker distanceMarker;

    private LatLng currentUserLocation;
    private int jobGroupId;
    private JSONObject userInfoData;
    private String token;
    //    private Handler locationUpdateHandler = new Handler();
//    private static final long LOCATION_UPDATE_INTERVAL = 5 * 60 * 1000; // 5分钟
//
//    private Runnable locationUpdateRunnable = new Runnable() {
//        @Override
//        public void run() {
//            updateUserLocation();
//            locationUpdateHandler.postDelayed(this, LOCATION_UPDATE_INTERVAL);
//        }
//    };

    private void loadSingleLabel(int labelId) {
        OkHttpClient client = new OkHttpClient();
        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(API_BASE_URL + "/app-api/linban/label/get?id=" + labelId)
//                .addHeader("Authorization", "Bearer " + getToken())
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                requireActivity().runOnUiThread(() ->
                        {
                            if(dev) {
                                Toast.makeText(requireActivity(), "加载标注失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        }
                );
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String responseData = response.body().string();
                    JSONObject jsonObject = new JSONObject(responseData);
                    if (jsonObject.getInt("code") != 0) throw new Exception(jsonObject.getString("msg"));

                    JSONObject labelData = jsonObject.getJSONObject("data");
                    if (labelData == null) throw new Exception("标注数据为空");

                    // 转换为现有MarkData结构
                    MarkData markData = parseToMarkData(labelData);

                    // 主线程更新UI
                    requireActivity().runOnUiThread(() -> {
                        // 处理重复标注（根据ID判断）
                        int index = findMarkIndexById(markData.getId());
                        if (index != -1) {
                            markList.set(index, markData); // 更新现有标注
                        } else {
                            markList.add(markData); // 添加新标注
                        }
                        renderMarksOnMap(); // 触发重新渲染
                    });

                } catch (Exception e) {
                    e.printStackTrace();
                    requireActivity().runOnUiThread(() ->
                            {
                                if(dev) Toast.makeText(requireActivity(), "解析标注失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                                Log.e(TAG, "onResponse: "+ e.getMessage() );
                            }
                    );
                }
            }
        });
    }
    private MarkData parseToMarkData(JSONObject labelData) throws JSONException {
        MarkData mark = new MarkData();
        mark.setId(labelData.getInt("id"));
        mark.setLabelName(labelData.getString("labelName"));
        mark.setLabelRemark(labelData.getString("labelRemark"));
        mark.setUserId(labelData.getInt("userId"));

        // 处理dataJson字段（假设返回的是JSON字符串，需转义处理）
        String dataJsonStr = labelData.getString("dataJson");
        // 示例转义处理（根据实际数据格式调整）
//        dataJsonStr = dataJsonStr.replace("DataJsonVO(", "{")
//                .replace(")", "}")
//                .replace("super=", "\"super\":")
//                .replace("type=", "\"type\":")
//                .replace("geometry=", "\"geometry\":")
//                .replace("properties=", "\"properties\":");

        mark.setDataJson(new JSONObject(dataJsonStr)); // 设置为JSONObject
        return mark;
    }
    private int findMarkIndexById(int id) {
        for (int i = 0; i < markList.size(); i++) {
            if (markList.get(i).getId() == id) return i;
        }
        return -1;
    }

    private String getToken() {
        return requireActivity().getSharedPreferences("user_info", MODE_PRIVATE)
                .getString("token", "");
    }

    public void setMsgLocation(double lon, double lat, String des,String a, String b) {

        if(des != null){
            try {
                int labelId = Integer.parseInt(des);
                loadSingleLabel(labelId); // 加载单标注
            } catch (NumberFormatException e) {
                if(dev) if(dev) Toast.makeText(requireActivity(), "标注ID格式错误",Toast.LENGTH_SHORT).show();
            }

        }
        //        aMap.addMarker(new MarkerOptions()
//                .position(new LatLng(lat, lon))
//                .icon(BitmapDescriptorFactory.fromBitmap(BitmapFactory
//                        .decodeResource(getResources(), R.drawable.ic_map_marker)))
//                .draggable(true));
        aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), 15));
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentMapBinding.inflate(getLayoutInflater());
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        try {
            if(dev) Toast.makeText(requireActivity(), "加载地图请稍等", Toast.LENGTH_SHORT).show();
            originalIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.pointer1);
            userOriginIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.map_positioning);
            scaledIcon = Bitmap.createScaledBitmap(originalIcon, 15, 15, false);
            userMarker = Bitmap.createScaledBitmap(originalIcon, 20, 20, false);

            // 初始化基础视图
            initBaseViews();

            // 初始化地图
            initMap(savedInstanceState);

            // 初始化功能
            initFeatures();

            // 加载标注列表
            loadMarkList();

            // 加载用户位置
            getUserInfo();
//            //显示定位蓝点
//            showBluepoint();
            dbHelper = new LocationDBHelper(requireActivity());
            checkNetworkStatus();

            // 初始化当前用户
            SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
            int userId = sp.getInt("userId", 0);
            String username = sp.getString("username", "");
            currentUser = new User(userId, username);

        } catch (Exception e) {
            if(dev) Toast.makeText(requireActivity(), "初始化失败: " + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    private void initBaseViews() {
        binding.btnMenu.setOnClickListener(v -> showNavigationMenu());
    }

    private void initMap(Bundle savedInstanceState) {
        mapView = binding.mapView;
        if (mapView != null) {
            mapView.onCreate(savedInstanceState);
            aMap = mapView.getMap();

            if (aMap != null) {
                // 设置卫星地图
                aMap.setMapType(AMap.MAP_TYPE_SATELLITE);

                // 自定义地图样式
                aMap.getUiSettings().setRotateGesturesEnabled(false); // 禁用旋转手势
                aMap.getUiSettings().setTiltGesturesEnabled(false);   // 禁用倾斜手势
                aMap.setMapType(AMap.MAP_TYPE_SATELLITE);             // 设置为卫星地图
                aMap.getUiSettings().setZoomControlsEnabled(true);    // 显示缩放按钮
                aMap.getUiSettings().setScaleControlsEnabled(true);   // 显示比例尺
                aMap.getUiSettings().setCompassEnabled(true);         // 显示指南针

                // 设置监听器
                aMap.setOnMapClickListener(this);
                aMap.setOnMarkerClickListener(this);
            } else {
                throw new RuntimeException("地图初始化失败");
            }
        } else {
            throw new RuntimeException("找不到地图视图");
        }
    }

    private void initFeatures() {
        setupBottomNavigation();
        setupSearchView();
        setupDrawTools();
        setupMapDrawTools();
        setupMarkList();
    }

    private boolean checkLoginStatus() {
        try {
            SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
            String token = sp.getString("token", null);
            userId = sp.getInt("userId", 0);

            if (token == null || userId == 0) {
                return false;
            }

            // 验证token是否有效
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private void setupMarkList() {
        markListDialog = new BottomSheetDialog(requireActivity());
        markListDialog.setContentView(R.layout.layout_mark_list);

        RecyclerView recyclerView = markListDialog.findViewById(R.id.recycler_marks);
        recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity()));

        markListAdapter = new MarkListAdapter(markList, mark -> {
            // 点击标注项时，定位到对应位置
            try {
                JSONObject geometry = mark.getDataJson().getJSONObject("geometry");
                String type = geometry.getString("type");
                JSONArray coordinates = geometry.getJSONArray("coordinates");

                // TODO: 实现地图定位和显示详情
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        recyclerView.setAdapter(markListAdapter);
    }

    private void loadMarkList() {
        SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
        String token = sp.getString("token", "");
        int userId = sp.getInt("userId", 0);

        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(API_BASE_URL + "/app-api/linban/label/list?userId=" + userId)
                .addHeader("Authorization", "Bearer " + token)
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                requireActivity().runOnUiThread(() -> {
                    if(dev) Toast.makeText(requireActivity(),
                            "加载失败: " + e.getMessage(),  Toast.LENGTH_SHORT).show();
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String responseData = response.body().string();
                    JSONObject jsonObject = new JSONObject(responseData);
                    if (jsonObject.getInt("code") == 0) {
                        JSONArray data = jsonObject.getJSONArray("data");
                        List<MarkData> newMarkList = new ArrayList<>();

                        for (int i = 0; i < data.length(); i++) {
                            JSONObject item = data.getJSONObject(i);
                            MarkData mark = new MarkData();
                            mark.setId(item.getInt("id"));
                            mark.setLabelName(item.getString("labelName"));
                            mark.setLabelRemark(item.getString("labelRemark"));
                            mark.setDataJson(item.getJSONObject("dataJson"));
                            mark.setUserId(item.getInt("userId"));
                            mark.setCreateTime(item.getLong("createTime"));
                            mark.setUpdateTime(item.getLong("updateTime"));
                            newMarkList.add(mark);
                        }

                        requireActivity().runOnUiThread(() -> {
                            markList.clear();
                            markList.addAll(newMarkList);
                            markListAdapter.notifyDataSetChanged();
                            renderMarksOnMap();
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void renderMarksOnMap() {
        clearLoadedMarks();
        markerMap.clear();

        for (MarkData mark : markList) {
            try {
                JSONObject geometry = mark.getDataJson().getJSONObject("geometry");
                JSONObject properties = mark.getDataJson().getJSONObject("properties");
                String type = geometry.getString("type");
                JSONArray coordinates = geometry.getJSONArray("coordinates");
                int markColor = Color.parseColor(properties.getString("color"));
                float markWidth = (float) properties.getDouble("lineWidth");

                switch (type) {
                    case "Point":
                        double lng = coordinates.getDouble(0);
                        double lat = coordinates.getDouble(1);
                        addLabelMarker(new LatLng(lat, lng), mark);
                        break;

                    case "LineString":
                        List<LatLng> linePoints = new ArrayList<>();
                        for (int i = 0; i < coordinates.length(); i++) {
                            JSONArray point = coordinates.getJSONArray(i);
                            linePoints.add(new LatLng(point.getDouble(1), point.getDouble(0)));
                        }

                        // 添加线条
                        Polyline polyline = aMap.addPolyline(new PolylineOptions()
                                .addAll(linePoints)
                                .color(markColor)
                                .width(markWidth));
                        loadedPolylines.add(polyline);

                        // 显示每段线段的长度
                        for (int i = 0; i < linePoints.size() - 1; i++) {
                            LatLng start = linePoints.get(i);
                            LatLng end = linePoints.get(i + 1);
                            double distance = AMapUtils.calculateLineDistance(start, end);
                            LatLng center = new LatLng(
                                    (start.latitude + end.latitude) / 2,
                                    (start.longitude + end.longitude) / 2
                            );

                            MarkerOptions markerOptions = new MarkerOptions()
                                    .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                                    .position(center)
                                    .title(String.format("%.1f米", distance))
                                    .anchor(0.5f, 0.5f);
                            Marker marker = aMap.addMarker(markerOptions);
                            marker.showInfoWindow();
                            labelMarkers.add(marker);
                        }

                        // 显示总长度
                        if (properties.has("length")) {
                            double totalLength = properties.getDouble("length");
                            LatLng lastPoint = linePoints.get(linePoints.size() - 1);
                            MarkerOptions markerOptions = new MarkerOptions()
//                                    .icon(BitmapDescriptorFactory.fromResource(R.mipmap.pointer1))
                                    .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                                    .position(lastPoint)
                                    .title(String.format("总长: %.1f米", totalLength))
                                    .anchor(0f, 0f);
                            Marker marker = aMap.addMarker(markerOptions);
                            marker.showInfoWindow();
                            labelMarkers.add(marker);
                        }
                        break;

                    case "Polygon":
                        JSONArray ring = coordinates.getJSONArray(0);

                        List<LatLng> polygonPoints = new ArrayList<>();
                        for (int i = 0; i < ring.length(); i++) {
                            JSONArray point = ring.getJSONArray(i);
                            polygonPoints.add(new LatLng(point.getDouble(1), point.getDouble(0)));
                        }

                        // 添加多边形
                        Polygon polygon = aMap.addPolygon(new PolygonOptions()
                                .addAll(polygonPoints)
                                .strokeColor(markColor)
                                .strokeWidth(markWidth)
                                .fillColor(Color.argb(50, Color.red(markColor),
                                        Color.green(markColor), Color.blue(markColor))));
                        loadedPolygons.add(polygon);

                        polygonMarkMap.put(polygon, mark);

                        // 在顶点位置添加标注点（新增代码）
                        for (LatLng vertex : polygonPoints) {
                            addLabelMarker(vertex, mark);
                        }

                        // 显示面积和周长（保留中心信息）
                        if (properties.has("area") && properties.has("perimeter")) {
                            double area = properties.getDouble("area");
                            double perimeter = properties.getDouble("perimeter");
                            LatLng center = calculatePolygonCenter(polygonPoints);

                            MarkerOptions markerOptions = new MarkerOptions()
                                    .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                                    .position(center)
                                    .title(String.format("面积: %.1f平方米\n周长: %.1f米", area, perimeter))
                                    .anchor(0.5f, 0.5f);
                            Marker marker = aMap.addMarker(markerOptions);
                            marker.showInfoWindow();
                            labelMarkers.add(marker);
                        }
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void addLabelMarker(LatLng position, MarkData mark) {
        MarkerOptions markerOptions = new MarkerOptions()
                .position(position)
                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.pointer1))
                .title(mark.getLabelName())
                .snippet(mark.getLabelRemark())
//                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.pointer1))
                .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                .anchor(0.5f, 1.0f);  // 将图标底部中心作为锚点

        Marker marker = aMap.addMarker(markerOptions);
        labelMarkers.add(marker);
        markerMap.put(marker.getId(), mark);
    }

    private int getColorFromJson(JSONObject dataJson) {
        try {
            JSONObject properties = dataJson.getJSONObject("properties");
            String colorStr = properties.getString("color");
            if (colorStr != null && !colorStr.isEmpty()) {
                return Color.parseColor(colorStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Color.parseColor("#4285F4"); // 默认蓝色
    }

    private float getWidthFromJson(JSONObject dataJson) {
        try {
            JSONObject properties = dataJson.getJSONObject("properties");
            return (float) properties.getDouble("lineWidth");
        } catch (Exception e) {
            return 3.0f;
        }
    }

    private LatLng calculatePolygonCenter(List<LatLng> points) {
        double lat = 0, lng = 0;
        int size = points.size();
        for (LatLng point : points) {
            lat += point.latitude;
            lng += point.longitude;
        }
        return new LatLng(lat / size, lng / size);
    }

    private void clearLoadedMarks() {
        for (Marker marker : labelMarkers) marker.remove();
        for (Polyline polyline : loadedPolylines) polyline.remove();
        for (Polygon polygon : loadedPolygons) polygon.remove();
        labelMarkers.clear();
        loadedPolylines.clear();
        loadedPolygons.clear();

        polygonMarkMap.clear();
    }

    private void setupMapDrawTools() {
        binding.btnUndo.setOnClickListener(this);
        binding.btnRedo.setOnClickListener(this);
        binding.btnClear.setOnClickListener(this);
    }

    private void setupBottomNavigation() {
        binding.bottomNavigation.setOnItemSelectedListener(item -> {
            int id = item.getItemId();
            if (id == R.id.navigation_map) {
                hideDrawTools();
                return true;
            } else if (id == R.id.navigation_marks) {
                markListDialog.show();
                return true;
            } else if (id == R.id.navigation_draw) {
                showDrawTools();
                return true;
            } else if (id == R.id.navigation_command) {
                startActivity(new Intent(requireActivity(), CommandCenterActivity.class));
                return true;
            }
            return false;
        });
    }

    private void setupSearchView() {
        binding.searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                startActivity(new Intent(requireActivity(), HistoryDataActivity.class));
                return true;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return false;
            }
        });
    }

    private void setupDrawTools() {
        drawToolsDialog = new BottomSheetDialog(requireActivity());
        drawToolsDialog.setContentView(R.layout.layout_draw_tools);

        drawToolsDialog.findViewById(R.id.btn_marker).setOnClickListener(v -> {
            clearCurrentDrawing();
            currentDrawMode = 1;
            updateDrawHint("点击地图添加标记点");
            drawToolsDialog.dismiss();
            showMapDrawTools();
        });

        drawToolsDialog.findViewById(R.id.btn_polyline).setOnClickListener(v -> {
            clearCurrentDrawing();
            currentDrawMode = 2;
            updateDrawHint("点击地图绘制折线，双击结束绘制");
            drawPoints.clear();
            drawToolsDialog.dismiss();
            showMapDrawTools();
        });

        drawToolsDialog.findViewById(R.id.btn_polygon).setOnClickListener(v -> {
            clearCurrentDrawing();
            currentDrawMode = 3;
            updateDrawHint("点击地图绘制多边形，双击结束绘制");
            drawPoints.clear();
            drawToolsDialog.dismiss();
            showMapDrawTools();
        });

        // 设置初始选中的颜色
        View[] colorViews = new View[5];
        colorViews[0] = drawToolsDialog.findViewById(R.id.color_blue);
        colorViews[1] = drawToolsDialog.findViewById(R.id.color_light_blue);
        colorViews[2] = drawToolsDialog.findViewById(R.id.color_green);
        colorViews[3] = drawToolsDialog.findViewById(R.id.color_yellow);
        colorViews[4] = drawToolsDialog.findViewById(R.id.color_red);

        // 设置初始选中的颜色
        colorViews[0].setBackgroundResource(R.drawable.circle_color_selected);
//        for (int i = 1; i < colorViews.length; i++) {
//            colorViews[i].setBackgroundResource(R.drawable.circle_color_normal);
//        }

        // 更新颜色选择反馈
        View.OnClickListener colorClickListener = v -> {
            // 重置所有颜色选择的边框
            for (View colorView : colorViews) {
//                if (colorView == v) {
//                    colorView.setBackgroundResource(R.drawable.circle_color_selected);
//                } else {
//                    colorView.setBackgroundResource(R.drawable.circle_color_normal);
//                }
            }

            if (v.getId() == R.id.color_blue) currentColor = Color.parseColor("#4285F4");
            else if (v.getId() == R.id.color_light_blue) currentColor = Color.parseColor("#03A9F4");
            else if (v.getId() == R.id.color_green) currentColor = Color.parseColor("#4CAF50");
            else if (v.getId() == R.id.color_yellow) currentColor = Color.parseColor("#FFC107");
            else if (v.getId() == R.id.color_red) currentColor = Color.parseColor("#F44336");

            updateCurrentDrawable();
        };

        drawToolsDialog.findViewById(R.id.color_blue).setOnClickListener(colorClickListener);
        drawToolsDialog.findViewById(R.id.color_light_blue).setOnClickListener(colorClickListener);
        drawToolsDialog.findViewById(R.id.color_green).setOnClickListener(colorClickListener);
        drawToolsDialog.findViewById(R.id.color_yellow).setOnClickListener(colorClickListener);
        drawToolsDialog.findViewById(R.id.color_red).setOnClickListener(colorClickListener);

        SeekBar widthSeekBar = drawToolsDialog.findViewById(R.id.seekbar_width);
        widthSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                currentWidth = progress + 1;
                updateCurrentDrawable();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });

        Button btnSave = drawToolsDialog.findViewById(R.id.btn_save);
        btnSave.setOnClickListener(v -> saveDrawing());

        Button btnCancel = drawToolsDialog.findViewById(R.id.btn_cancel);
        btnCancel.setOnClickListener(v -> {
            clearCurrentDrawing();
            drawToolsDialog.dismiss();
            hideDrawTools();
        });

        etMarkName = drawToolsDialog.findViewById(R.id.et_mark_name);
        etMarkDesc = drawToolsDialog.findViewById(R.id.et_mark_desc);
    }

    private void showDrawTools() {
        drawToolsDialog.show();
    }

    private void showMapDrawTools() {
        binding.tvDrawHint.setVisibility(View.VISIBLE);
        binding.layoutDrawTools.setVisibility(View.VISIBLE);
    }

    private void hideDrawTools() {
        currentDrawMode = 0;
        binding.tvDrawHint.setVisibility(View.GONE);
        binding.layoutDrawTools.setVisibility(View.GONE);
        clearCurrentDrawing();
    }

    private void updateDrawHint(String hint) {
        binding.tvDrawHint.setText(hint);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_undo) {
            undoLastPoint();
        } else if (id == R.id.btn_redo) {
            // TODO: 实现重做功能
        } else if (id == R.id.btn_clear) {
            clearCurrentDrawing();
        }
    }

    private void undoLastPoint() {
        if (drawPoints.size() > 0) {
            drawPoints.remove(drawPoints.size() - 1);
            updateCurrentDrawable();
        }
    }

    private void checkPolygonClick(LatLng clickPoint) {
        for (Map.Entry<Polygon, MarkData> entry : polygonMarkMap.entrySet()) {
            Polygon polygon = entry.getKey();
            if (isPointInPolygon(clickPoint, polygon.getPoints())) {
                MarkData markData = entry.getValue();
                showMarkOperationDialog(markData, null);
                return;
            }
        }
    }

    public boolean isPointInPolygon(LatLng point, List<LatLng> polygonPoints) {
        int n = polygonPoints.size();
        boolean inside = false;
        for (int i = 0, j = n - 1; i < n; j = i++) {
            LatLng p1 = polygonPoints.get(i);
            LatLng p2 = polygonPoints.get(j);
            // 判断点是否在边的垂直范围内
            if (point.latitude > Math.min(p1.latitude, p2.latitude) &&
                    point.latitude <= Math.max(p1.latitude, p2.latitude) &&
                    point.longitude <= Math.max(p1.longitude, p2.longitude) &&
                    (p1.latitude > p2.latitude) != (point.latitude > (p2.latitude - p1.latitude) *
                            (point.longitude - p1.longitude) / (p2.longitude - p1.longitude) + p1.latitude)) {
                inside = !inside;
            }
        }
        return inside;
    }

    @Override
    public void onMapClick(LatLng latLng) {
        if (currentDrawMode == 0) {
            // 仅在地图普通点击模式下检测多边形点击
            checkPolygonClick(latLng);
            return;
        }


        // 清除之前的临时标记
        clearTempMarkers();

        switch (currentDrawMode) {
            case 1: // 点
                if (currentMarker != null) currentMarker.remove();
                currentMarker = aMap.addMarker(new MarkerOptions()
                        .position(latLng)
//                        .icon(BitmapDescriptorFactory.fromResource(R.mipmap.pointer1))
                        .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                        .anchor(0.5f, 1.0f)  // 将图标底部中心作为锚点
                        .draggable(true));
                drawPoints.clear();
                drawPoints.add(latLng);
                showSaveDialog();
                break;
            case 2: // 线
                drawPoints.add(latLng);

                // 添加顶点标记
                Marker vertexMarker = aMap.addMarker(new MarkerOptions()
                        .position(latLng)
//                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_vertex))
                        .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))

                        .anchor(0.5f, 0.5f));
                tempMarkers.add(vertexMarker);

                if (currentPolyline != null) currentPolyline.remove();
                if (drawPoints.size() > 1) {
                    // 绘制线
                    currentPolyline = aMap.addPolyline(new PolylineOptions()
                            .addAll(drawPoints)
                            .color(currentColor)
                            .width(currentWidth)
                            .useGradient(true));  // 使用渐变效果使线条更平滑

                    // 更新距离信息
                    updatePolylineDistance();
                }
                break;
            case 3: // 面
                drawPoints.add(latLng);

                // 添加顶点标记
                Marker polygonVertex = aMap.addMarker(new MarkerOptions()
                        .position(latLng)
//                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_vertex))
                        .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                        .anchor(0.5f, 0.5f));
                tempMarkers.add(polygonVertex);

                if (currentPolygon != null) currentPolygon.remove();
                if (drawPoints.size() > 2) {
                    // 计算填充颜色
                    int fillColor = Color.argb(128,
                            Color.red(currentColor),
                            Color.green(currentColor),
                            Color.blue(currentColor));

                    // 绘制多边形
                    currentPolygon = aMap.addPolygon(new PolygonOptions()
                            .addAll(drawPoints)
                            .strokeColor(currentColor)
                            .strokeWidth(currentWidth)
                            .fillColor(fillColor));

                    // 更新面积和周长信息
                    updatePolygonMeasurements();
                }
                break;
        }
    }

    private void showSaveDialog() {
        if (drawPoints.size() < 1) return;

        if (currentDrawMode == 1 ||
                (currentDrawMode == 2 && drawPoints.size() > 1) ||
                (currentDrawMode == 3 && drawPoints.size() > 2)) {
            drawToolsDialog.show();
        }
    }

    private void updateCurrentDrawable() {
        if (currentPolyline != null) {
            currentPolyline.remove();
            if (drawPoints.size() > 1) {
                currentPolyline = aMap.addPolyline(new PolylineOptions()
                        .addAll(drawPoints)
                        .color(currentColor)
                        .width(currentWidth)
                        .useGradient(true));  // 添加渐变效果
            }
        }
        if (currentPolygon != null) {
            currentPolygon.remove();
            if (drawPoints.size() > 2) {
                currentPolygon = aMap.addPolygon(new PolygonOptions()
                        .addAll(drawPoints)
                        .strokeColor(currentColor)
                        .strokeWidth(currentWidth)
                        .fillColor(Color.argb(128, Color.red(currentColor),
                                Color.green(currentColor), Color.blue(currentColor))));
            }
        }
    }

    private void clearCurrentDrawing() {
        if (currentMarker != null) currentMarker.remove();
        if (currentPolyline != null) currentPolyline.remove();
        if (currentPolygon != null) currentPolygon.remove();
        drawPoints.clear();
    }

    private void saveDrawing() {
        if (drawPoints.isEmpty()) {
            if(dev) Toast.makeText(requireActivity(), "请先绘制图形",  Toast.LENGTH_SHORT).show();
            return;
        }

        String name = etMarkName.getText().toString();
        String desc = etMarkDesc.getText().toString();

        if (name.isEmpty()) {
            if(dev) Toast.makeText(requireActivity(), "请输入标注名称",  Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            JSONObject geojson = new JSONObject();
            geojson.put("type", "Feature");

            JSONObject properties = new JSONObject();
            properties.put("color", String.format("#%06X", (0xFFFFFF & currentColor)));
            properties.put("lineWidth", currentWidth);
            properties.put("title", name);
            properties.put("description", desc);

            // 添加面积和周长的保存
            if (currentDrawMode == 3 && drawPoints.size() > 2) {
                double area = AMapUtils.calculateArea(drawPoints);
                double perimeter = 0;
                for (int i = 0; i < drawPoints.size(); i++) {
                    LatLng p1 = drawPoints.get(i);
                    LatLng p2 = drawPoints.get((i + 1) % drawPoints.size());
                    perimeter += AMapUtils.calculateLineDistance(p1, p2);
                }
                properties.put("area", area);
                properties.put("perimeter", perimeter);
            } else if (currentDrawMode == 2 && drawPoints.size() > 1) {
                // 保存线段总长度
                double totalLength = 0;
                for (int i = 0; i < drawPoints.size() - 1; i++) {
                    totalLength += AMapUtils.calculateLineDistance(drawPoints.get(i), drawPoints.get(i + 1));
                }
                properties.put("length", totalLength);
            }

            geojson.put("properties", properties);

            JSONObject geometry = new JSONObject();
            switch (currentDrawMode) {
                case 1:
                    geometry.put("type", "Point");
                    JSONArray coordinates = new JSONArray();
                    coordinates.put(drawPoints.get(0).longitude);
                    coordinates.put(drawPoints.get(0).latitude);
                    geometry.put("coordinates", coordinates);
                    break;
                case 2:
                    geometry.put("type", "LineString");
                    JSONArray lineCoords = new JSONArray();
                    for (LatLng point : drawPoints) {
                        JSONArray coord = new JSONArray();
                        coord.put(point.longitude);
                        coord.put(point.latitude);
                        lineCoords.put(coord);
                    }
                    geometry.put("coordinates", lineCoords);
                    break;
                case 3:
                    geometry.put("type", "Polygon");
                    JSONArray polygonCoords = new JSONArray();
                    JSONArray ring = new JSONArray();
                    for (LatLng point : drawPoints) {
                        JSONArray coord = new JSONArray();
                        coord.put(point.longitude);
                        coord.put(point.latitude);
                        ring.put(coord);
                    }
                    // 闭合多边形
                    if (!drawPoints.get(0).equals(drawPoints.get(drawPoints.size() - 1))) {
                        JSONArray coord = new JSONArray();
                        coord.put(drawPoints.get(0).longitude);
                        coord.put(drawPoints.get(0).latitude);
                        ring.put(coord);
                    }
                    polygonCoords.put(ring);
                    geometry.put("coordinates", polygonCoords);
                    break;
            }
            geojson.put("geometry", geometry);

            // 创建请求体
            SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
            String token = sp.getString("token", "");
            int userId = sp.getInt("userId", 0);

            JSONObject requestBody = new JSONObject();
            requestBody.put("labelName", name);
            requestBody.put("labelRemark", desc);
            requestBody.put("dataJson", geojson);
            requestBody.put("userId", userId);



            RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody.toString());
            okhttp3.Request request = new okhttp3.Request.Builder()
                    .url(BASE_URL + "/app-api/linban/label/create")
                    .addHeader("Authorization", "Bearer " + token)
                    .post(body)
                    .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    requireActivity().runOnUiThread(() -> {
                        if(dev) Toast.makeText(requireActivity(),
                                "保存失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                    });
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        String responseData = response.body().string();
                        JSONObject jsonObject = new JSONObject(responseData);
//                        if(dev) Toast.makeText(requireActivity(), jsonObject.toString(), Toast.LENGTH_SHORT).show();
                        if (jsonObject.getInt("code") == 0) {
                            requireActivity().runOnUiThread(() -> {
                                if(dev) Toast.makeText(requireActivity(), "保存成功",  Toast.LENGTH_SHORT).show();
                                clearCurrentDrawing();
                                drawToolsDialog.dismiss();
                                hideDrawTools();
                                etMarkName.setText("");
                                etMarkDesc.setText("");
                                // 重新加载标注列表，但保持用户标注
                                loadMarkList();
                                loadUserLocation(); // 重新加载用户位置
                            });
                        } else {

                            requireActivity().runOnUiThread(() -> {
                                try {
                                    if(dev) Toast.makeText(requireActivity(),
                                            "保存失败: " + jsonObject.getString("msg"),  Toast.LENGTH_SHORT).show();
                                } catch (JSONException e) {
                                    throw new RuntimeException(e);
                                }
                            });
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "onResponse: "+ e.getMessage() );
                        e.printStackTrace();
                        requireActivity().runOnUiThread(() -> {
                            if(dev) Toast.makeText(requireActivity(),
                                    "保存失败: " + e.getMessage(),  Toast.LENGTH_SHORT).show();
                        });
                    }
                }
            });

        } catch (Exception e) {
            if(dev) Toast.makeText(requireActivity(), "保存失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    private void clearTempMarkers() {
        for (Marker marker : tempMarkers) {
            marker.remove();
        }
        tempMarkers.clear();
        if (distanceMarker != null) {
            distanceMarker.remove();
            distanceMarker = null;
        }
    }

    private void updatePolylineDistance() {
        if (drawPoints.size() < 2) return;

        // 计算总长度
        double totalLength = 0;
        for (int i = 0; i < drawPoints.size() - 1; i++) {
            totalLength += AMapUtils.calculateLineDistance(drawPoints.get(i), drawPoints.get(i + 1));
        }

        // 在最新线段的中点显示距离
        LatLng lastPoint = drawPoints.get(drawPoints.size() - 1);
        LatLng prevPoint = drawPoints.get(drawPoints.size() - 2);
        LatLng center = new LatLng(
                (lastPoint.latitude + prevPoint.latitude) / 2,
                (lastPoint.longitude + prevPoint.longitude) / 2
        );

        String distanceInfo = String.format("总长: %.2f米", totalLength);

        if (distanceMarker != null) {
            distanceMarker.remove();
        }

        distanceMarker = aMap.addMarker(new MarkerOptions()
                .position(center)
                .title(distanceInfo)
                .visible(true));
        distanceMarker.showInfoWindow();
        tempMarkers.add(distanceMarker);
    }

    private void updatePolygonMeasurements() {
        if (drawPoints.size() < 3) return;

        // 计算面积
        double area = AMapUtils.calculateArea(drawPoints);

        // 计算周长
        double perimeter = 0;
        for (int i = 0; i < drawPoints.size(); i++) {
            LatLng p1 = drawPoints.get(i);
            LatLng p2 = drawPoints.get((i + 1) % drawPoints.size());
            perimeter += AMapUtils.calculateLineDistance(p1, p2);
        }

        // 在多边形中心显示信息
        LatLng center = calculatePolygonCenter(drawPoints);
        String measureInfo = String.format("面积: %.1f平方米\n周长: %.2f米", area, perimeter);

        if (distanceMarker != null) {
            distanceMarker.remove();
        }

        distanceMarker = aMap.addMarker(new MarkerOptions()
                .icon(BitmapDescriptorFactory.fromBitmap(scaledIcon))
                .position(center)
                .title(measureInfo)
                .visible(true));
        distanceMarker.showInfoWindow();
        tempMarkers.add(distanceMarker);
    }

    private void requestPermissino() {
        /**    地图所需权限 :
         * roup:android.permission-group.LOCATION(定位)
         * android.permission.ACCESS_FINE_LOCATION(通过gps获取定位权限)
         * android.permission.ACCESS_COARSE_LOCATION(通过wifi和移动基站获取定位权限)
         **/
        if (ContextCompat.checkSelfPermission(requireActivity(),
                // 未开启定位权限
                Manifest.permission.ACCESS_FINE_LOCATION) != PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }

    @SuppressLint("LogNotTimber")
    @Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (amapLocation != null) {
            if (amapLocation.getErrorCode() == 0) {
                requestPermissino();
                //定位成功回调信息，设置相关消息
                amapLocation.getLocationType();//获取当前定位结果来源，如网络定位结果，详见定位类型表
                amapLocation.getLatitude();//获取纬度
                amapLocation.getLongitude();//获取经度
                amapLocation.getAccuracy();//获取精度信息
                //todo 这里加载组内成员的实时定位信息 以及上传自己的用户定位
                currentUserLocation = new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude());
                // TODO log
                if(dev) Toast.makeText(requireActivity(), "获取到高德定位 : " +currentUserLocation.latitude + "  " +currentUserLocation.longitude, Toast.LENGTH_SHORT).show();
                // 加载同组用户
                loadGroupUsers(jobGroupId, token);
                //上传经纬度信息
                updateLocation(amapLocation.getLatitude(),amapLocation.getLongitude());
            } else {
                //显示错误信息ErrCode是错误码，errInfo是错误信息，详见错误码表。
                Log.e(TAG, "location Error, ErrCode:"
                        + amapLocation.getErrorCode() + ", errInfo:"
                        + amapLocation.getErrorInfo());
            }
        }
    }

    private void showBluepoint() {
        MyLocationStyle myLocationStyle;
        myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
        myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER);
        aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
        aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示，非必需设置。
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
    }

    private void getUserInfo() {
        binding.btnLocation.setOnClickListener(view -> {
            if (currentUserLocation != null) {
                if(dev) Toast.makeText(requireActivity(), "获取到高德定位 : " +currentUserLocation.latitude + "  " +currentUserLocation.longitude, Toast.LENGTH_SHORT).show();
                aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentUserLocation, 15));
            }
        });

        SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
        token = sp.getString("token", "");
        int userId = sp.getInt("userId", 0);
        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(API_BASE_URL + "/app-api/linban/user/get?id=" + userId)
                .addHeader("Authorization", "Bearer " + token)
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                requireActivity().runOnUiThread(() -> {
                    if(dev) Toast.makeText(requireActivity(),
                            "获取位置失败: " + e.getMessage(),  Toast.LENGTH_SHORT).show();
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String responseData = response.body().string();
                    Log.e(TAG, "onResponse: " + responseData);
                    JSONObject jsonObject = new JSONObject(responseData);
                    if (jsonObject.getInt("code") == 0) {
                        userInfoData = jsonObject.getJSONObject("data");
                        jobGroupId = userInfoData.getInt("jobGroupId");
                        // 移动地图到当前用户位置
                        requireActivity().runOnUiThread(() -> {
                            loadUserLocation();
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    requireActivity().runOnUiThread(() -> {
                        if(dev) Toast.makeText(requireActivity(),
                                "解析用户位置数据失败: " + e.getMessage(),  Toast.LENGTH_SHORT).show();
                    });
                }
            }
        });
    }

    private void loadUserLocation() {
        try {
            mlocationClient = new AMapLocationClient(requireActivity());
            //初始化定位参数
            mLocationOption = new AMapLocationClientOption();
            //设置定位监听
            mlocationClient.setLocationListener(this);
            //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
            mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //设置定位间隔,单位毫秒,默认为2000ms
            mLocationOption.setInterval(5 * 60 * 1000);
            //设置定位参数
            mlocationClient.setLocationOption(mLocationOption);
            // 此方法为每隔固定时间会发起一次定位请求，为了减少电量消耗或网络流量消耗，
            // 注意设置合适的定位时间的间隔（最小间隔支持为1000ms），并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后，在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下，定位无论成功与否，都无需调用stopLocation()方法移除请求，定位sdk内部会移除
            //启动定位
            mlocationClient.startLocation();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    private void loadGroupUsers(int jobGroupId, String token) {
        okhttp3.Request request = new okhttp3.Request.Builder()
                .url(API_BASE_URL + "/app-api/linban/user/list?jobGroupId=" + jobGroupId)
                .addHeader("Authorization", "Bearer " + token)
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                requireActivity().runOnUiThread(() -> {
                    if(dev) Toast.makeText(requireActivity(),
                            "获取同组用户失败: " + e.getMessage(),  Toast.LENGTH_SHORT).show();
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    String responseData = response.body().string();
                    SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
//                    Log.i(TAG, "userInfo: \n"+sp.getInt("userId", 0));

                    Log.i(TAG, "onResponse: "+responseData);
                    JSONObject jsonObject = new JSONObject(responseData);
                    if (jsonObject.getInt("code") == 0) {
                        JSONArray users = jsonObject.getJSONArray("data");
                        for (int i = 0; i < users.length(); i++) {
                            JSONObject user = users.getJSONObject(i);

                            addUserMarker(user,R.mipmap.map_positioning);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void addUserMarker(JSONObject userInfo,int icon) {
        requireActivity().runOnUiThread(() -> {
            try {
                // 创建自定义信息窗口的布局
                View markerView = getLayoutInflater().inflate(R.layout.marker_user_info, null);
                TextView tvName = markerView.findViewById(R.id.tv_user_name);
                TextView tvJob = markerView.findViewById(R.id.tv_user_job);

                tvName.setText(userInfo.getString("userName"));
                tvJob.setText(userInfo.getString("job"));

                // 将布局转换为Bitmap
                markerView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight());
                markerView.setDrawingCacheEnabled(true);
                markerView.buildDrawingCache();
                Bitmap bmp = Bitmap.createBitmap(markerView.getDrawingCache());
                markerView.setDrawingCacheEnabled(false);


                Marker marker = userMarkers.get(userInfo.getInt("id"));
                if (marker != null){
                    marker.remove();
                    userMarkers.remove(marker);
                }

                // 添加标记
                if(dev) Toast.makeText(requireActivity(), "获取到高德定位 : " +currentUserLocation.latitude + "  " +currentUserLocation.longitude, Toast.LENGTH_SHORT).show();
                MarkerOptions markerOptions = new MarkerOptions()
                        .position(currentUserLocation)
                        .icon(BitmapDescriptorFactory.fromResource(icon))
                        .anchor(0.5f, 1.0f) // 设置图标底部中心为锚点
                        .title(userInfo.getString("userName"))
                        .snippet(userInfo.getString("job"));
                Marker myMarker = aMap.addMarker(markerOptions);
                myMarker.setObject(userInfo.toString());
                userMarkers.put(userInfo.getInt("id"),myMarker);
            } catch (JSONException e) {
                e.printStackTrace();
            }
        });
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        LatLng position = marker.getPosition();
        if(dev) Toast.makeText(requireActivity(), "点击了地图 : " +position.latitude  + "  " + position.longitude,  Toast.LENGTH_SHORT).show();
        // 检查是否是临时标记点
        if (tempMarkers.contains(marker) || marker.equals(distanceMarker)) {
            return true;
        }

        // 获取标记点对应的数据
        MarkData markData = markerMap.get(marker.getId());
        if (markData != null) {
            showMarkOperationDialog(markData, marker);
            return true;
        }

        // 处理用户标记点点击
        try {
            String userInfoStr = (String) marker.getObject();
            if (userInfoStr != null) {
                JSONObject userInfo = new JSONObject(userInfoStr);
                showUserTrackDialog(userInfo);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    private void showMarkOperationDialog(MarkData markData, Marker marker) {
        String[] operations = {"修改", "删除", "分享"};
        new AlertDialog.Builder(requireActivity())
                .setTitle(markData.getLabelName())
                .setItems(operations, (dialog, which) -> {
                    switch (which) {
                        case 0: // 修改
                            showEditDialog(markData);
                            break;
                        case 1: // 删除
                            showDeleteConfirmDialog(markData);
                            break;
                        case 2: // 分享
                            shareMark(markData, marker);
                            break;
                    }
                })
                .show();
    }

    private void showEditDialog(MarkData markData) {
        BottomSheetDialog editDialog = new BottomSheetDialog(requireActivity());
        editDialog.setContentView(R.layout.layout_draw_tools);

        EditText etName = editDialog.findViewById(R.id.et_mark_name);
        EditText etDesc = editDialog.findViewById(R.id.et_mark_desc);
        etName.setText(markData.getLabelName());
        etDesc.setText(markData.getLabelRemark());

        // 设置颜色和线宽
        try {
            JSONObject properties = markData.getDataJson().getJSONObject("properties");
            currentColor = Color.parseColor(properties.getString("color"));
            currentWidth = (float) properties.getDouble("lineWidth");

            // 初始化颜色选择器状态
            View[] colorViews = new View[5];
            colorViews[0] = editDialog.findViewById(R.id.color_blue);
            colorViews[1] = editDialog.findViewById(R.id.color_light_blue);
            colorViews[2] = editDialog.findViewById(R.id.color_green);
            colorViews[3] = editDialog.findViewById(R.id.color_yellow);
            colorViews[4] = editDialog.findViewById(R.id.color_red);

            // 重置所有颜色选择的边框
//            for (View colorView : colorViews) {
//                colorView.setBackgroundResource(R.drawable.circle_color_normal);
//            }

            // 根据当前颜色设置选中状态
            String currentColorHex = String.format("#%06X", (0xFFFFFF & currentColor));
            if ("#4285F4".equals(currentColorHex))
                colorViews[0].setBackgroundResource(R.drawable.circle_color_selected);
            else if ("#03A9F4".equals(currentColorHex))
                colorViews[1].setBackgroundResource(R.drawable.circle_color_selected);
            else if ("#4CAF50".equals(currentColorHex))
                colorViews[2].setBackgroundResource(R.drawable.circle_color_selected);
            else if ("#FFC107".equals(currentColorHex))
                colorViews[3].setBackgroundResource(R.drawable.circle_color_selected);
            else if ("#F44336".equals(currentColorHex))
                colorViews[4].setBackgroundResource(R.drawable.circle_color_selected);

            // 设置颜色点击监听器
            View.OnClickListener colorClickListener = v -> {
                // 重置所有颜色选择的边框
//                for (View colorView : colorViews) {
//                    colorView.setBackgroundResource(R.drawable.circle_color_normal);
//                }

                // 设置选中的颜色边框
                v.setBackgroundResource(R.drawable.circle_color_selected);

                if (v.getId() == R.id.color_blue) currentColor = Color.parseColor("#4285F4");
                else if (v.getId() == R.id.color_light_blue)
                    currentColor = Color.parseColor("#03A9F4");
                else if (v.getId() == R.id.color_green) currentColor = Color.parseColor("#4CAF50");
                else if (v.getId() == R.id.color_yellow) currentColor = Color.parseColor("#FFC107");
                else if (v.getId() == R.id.color_red) currentColor = Color.parseColor("#F44336");
            };

//            for (View colorView : colorViews) {
//                colorView.setOnClickListener(colorClickListener);
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        editDialog.findViewById(R.id.btn_save).setOnClickListener(v -> {
            String newName = etName.getText().toString();
            String newDesc = etDesc.getText().toString();

            if (newName.isEmpty()) {
                if(dev) Toast.makeText(requireActivity(), "请输入标注名称", Toast.LENGTH_SHORT).show();
                return;
            }

            try {
                // 更新properties
                SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
                String token = sp.getString("token", "");
                int userId = sp.getInt("userId", 0);
                JSONObject properties = markData.getDataJson().getJSONObject("properties");
                properties.put("title", newName);
                properties.put("description", newDesc);
                properties.put("color", String.format("#%06X", (0xFFFFFF & currentColor)));
                properties.put("lineWidth", currentWidth);

                // 创建请求体
                JSONObject requestBody = new JSONObject();
                requestBody.put("labelName", newName);
                requestBody.put("labelRemark", newDesc);
                requestBody.put("dataJson", markData.getDataJson());
                requestBody.put("userId", userId);

                // 发送更新请求



                RequestBody body = RequestBody.create(JSON, requestBody.toString());
                okhttp3.Request request = new okhttp3.Request.Builder()
                        .url(BASE_URL + "/app-api/linban/label/update/" + markData.getId())
                        .addHeader("Authorization", "Bearer " + token)
                        .put(body)
                        .build();

                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        requireActivity().runOnUiThread(() -> {
                            if(dev) Toast.makeText(requireActivity(),
                                    "更新失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                        });
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        try {
                            String responseData = response.body().string();
                            JSONObject jsonObject = new JSONObject(responseData);
                            if (jsonObject.getInt("code") == 0) {
                                requireActivity().runOnUiThread(() -> {
                                    if(dev) Toast.makeText(requireActivity(), "更新成功", Toast.LENGTH_SHORT).show();
                                    editDialog.dismiss();
                                    loadMarkList(); // 重新加载标注列表
                                });
                            } else {
                                requireActivity().runOnUiThread(() -> {
                                    try {
                                        if(dev) Toast.makeText(requireActivity(),
                                                "更新失败: " + jsonObject.getString("msg"), Toast.LENGTH_SHORT).show();
                                    } catch (JSONException e) {
                                        throw new RuntimeException(e);
                                    }
                                });
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            requireActivity().runOnUiThread(() ->{
                                if(dev) Toast.makeText(requireActivity(),
                                        "更新失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                            });
                        }
                    }
                });

            } catch (Exception e) {
                if(dev) Toast.makeText(requireActivity(), "更新失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });

        editDialog.show();
    }

    private void showDeleteConfirmDialog(MarkData markData) {
        new AlertDialog.Builder(requireActivity())
                .setTitle("确认删除")
                .setMessage("确定要删除这个标注吗？")
                .setPositiveButton("确定", (dialog, which) -> {
                    okhttp3.Request request = new okhttp3.Request.Builder()
                            .url(BASE_URL + "/app-api/linban/label/delete?id=" + markData.getId())
                            .delete()
                            .build();

                    client.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            requireActivity().runOnUiThread(() -> {
                                if(dev) Toast.makeText(requireActivity(),
                                        "删除失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                            });
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            try {
                                String responseData = response.body().string();
                                JSONObject jsonObject = new JSONObject(responseData);
                                if (jsonObject.getInt("code") == 0) {
                                    requireActivity().runOnUiThread(() -> {
                                        if(dev) Toast.makeText(requireActivity(), "删除成功", Toast.LENGTH_SHORT).show();
                                        loadMarkList(); // 重新加载标注列表
                                    });
                                } else {
                                    requireActivity().runOnUiThread(() -> {
                                        try {
                                            if(dev) Toast.makeText(requireActivity(),
                                                    "删除失败: " + jsonObject.getString("msg"), Toast.LENGTH_SHORT).show();
                                        } catch (JSONException e) {
                                            throw new RuntimeException(e);
                                        }
                                    });
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                                requireActivity().runOnUiThread(() -> {
                                    if(dev) Toast.makeText(requireActivity(),
                                            "删除失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
                                });
                            }
                        }
                    });
                })
                .setNegativeButton("取消", null)
                .show();
    }

    private void shareMark(MarkData markData, Marker marker) {
        try {
            SelectTargetVM targetVM = Easy.installVM(SelectTargetVM.class)
                    .setIntention(SelectTargetVM.Intention.isCreateGroup);
            targetVM.setOnFinishListener(() -> {
                GroupVM groupVM = BaseApp.inst().getVMByCache(GroupVM.class);
                if (null == groupVM)
                    groupVM = new GroupVM();
                groupVM.selectedFriendInfo.getValue().clear();
                List<MultipleChoice> multipleChoices = targetVM.metaData.getValue();
                for (int i = 0; i < multipleChoices.size(); i++) {
                    MultipleChoice us = multipleChoices.get(i);
                    LatLng position = marker.getPosition();
                    double latitude = position.latitude;
                    double longitude = position.longitude;
//                    sendLatLonMsg(us.key, latitude, longitude,String.valueOf(markData.getId()));
                    sendLatLonMsg(us.key, latitude, longitude,markData.getLabelName(),markData);
                }

            });
            ARouter.getInstance().build(Routes.Group.SELECT_TARGET).navigation();
        } catch (Exception e) {
            if(dev) Toast.makeText(requireActivity(), "分享失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    private void sendLatLonMsg(String userID, double latitude, double longitude, String description,MarkData markData) {
        String labelId = String.valueOf(markData.getId());
        Message msg = OpenIMClient.getInstance().messageManager.createLocationMessage(latitude, longitude, labelId);

        //这里最好不要改变msg其他的变量
        msg.setStatus(MessageStatus.SENDING);
        OfflinePushInfo offlinePushInfo = new OfflinePushInfo();  // 离线推送的消息备注；不为null
        OpenIMClient.getInstance().messageManager.sendMessage(new OnMsgSendCallback() {
            @Override
            public void onError(int code, String error) {
                if(dev) Toast.makeText(requireActivity(), "分享失败: " + error, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onProgress(long progress) {
            }

            @Override
            public void onSuccess(Message message) {
                if(dev) Toast.makeText(requireActivity(), "分享成功!", Toast.LENGTH_SHORT).show();
            }
        }, msg, userID, "", offlinePushInfo);
    }

    private void showUserTrackDialog(JSONObject userInfo) {
        try {
            // 创建对话框布局
            AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
            View dialogView = getLayoutInflater().inflate(R.layout.dialog_user_info, null);

            // 设置用户信息
            TextView tvUserName = dialogView.findViewById(R.id.tv_user_name);
            TextView tvUserJob = dialogView.findViewById(R.id.tv_user_job);
            TextView tvUserGroup = dialogView.findViewById(R.id.tv_user_group);
            TextView tvUserAccount = dialogView.findViewById(R.id.tv_user_account);
            TextView tvUserStatus = dialogView.findViewById(R.id.tv_user_status);
            TextView tvLastActive = dialogView.findViewById(R.id.tv_last_active);

            tvUserName.setText("姓名: " + userInfo.getString("userName"));
            tvUserJob.setText("职位: " + userInfo.getString("job"));
            tvUserGroup.setText("工作组: " + userInfo.getString("jobGroup"));
            tvUserAccount.setText("账号: " + userInfo.getString("account"));
            tvUserStatus.setText("状态: " + (userInfo.getInt("isAlive") == 1 ? "在线" : "离线"));

            // 格式化最后活跃时间
            long lastAliveTime = userInfo.getLong("lastAliveTime");
            java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String lastActiveStr = sdf.format(new java.util.Date(lastAliveTime));
            tvLastActive.setText("最后活跃: " + lastActiveStr);

            builder.setView(dialogView)
                    .setTitle("用户详情")
                    .setPositiveButton("查看24小时轨迹", (dialog, which) -> {
                        try {
                            Intent intent = new Intent(requireActivity(), TrackPlaybackActivity.class);
                            intent.putExtra("userId", userInfo.getInt("id")); // 使用id字段
                            intent.putExtra("userName", userInfo.getString("userName"));
                            startActivity(intent);
                        } catch (JSONException e) {
                            e.printStackTrace();
                            if(dev) Toast.makeText(requireActivity(), "获取用户ID失败", Toast.LENGTH_SHORT).show();
                        }
                    })
                    .setNegativeButton("关闭", null)
                    .show();

        } catch (Exception e) {
            e.printStackTrace();
            if(dev) Toast.makeText(requireActivity(), "获取用户信息失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    private void startLocationUpdates() {
//        locationUpdateHandler.post(locationUpdateRunnable);
    }

    private void stopLocationUpdates() {
//        locationUpdateHandler.removeCallbacks(locationUpdateRunnable);
    }

    private void updateUserLocation() {
        if (currentUserLocation == null) return;

        try {
            JSONObject requestBody = new JSONObject();
            requestBody.put("userId", userId);
            requestBody.put("latitude", currentUserLocation.latitude);
            requestBody.put("longitude", currentUserLocation.longitude);

            SharedPreferences sp = requireActivity().getSharedPreferences("user_info", MODE_PRIVATE);
            String token = sp.getString("token", "");

            RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody.toString());
            okhttp3.Request request = new okhttp3.Request.Builder()
                    .url(API_UPDATE_LOCATION)
                    .addHeader("Authorization", "Bearer " + token)
                    .put(body)
                    .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        String responseData = response.body().string();
                        JSONObject jsonResponse = new JSONObject(responseData);
                        if (jsonResponse.getInt("code") != 0) {
                            System.out.println("更新位置失败: " + jsonResponse.getString("msg"));
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mapView != null) {
            mapView.onResume();
        }
        startLocationUpdates();
        // 检查网络状态
        checkNetworkStatus();
        // 尝试同步离线位置
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        requireActivity().registerReceiver(networkReceiver, filter);
        syncOfflineLocations();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mapView != null) {
            mapView.onPause();
        }
        stopLocationUpdates();
        requireActivity().unregisterReceiver(networkReceiver);

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        clearTempMarkers();
        if (mapView != null) {
            mapView.onDestroy();
        }
        stopLocationUpdates();
//        locationUpdateHandler.removeCallbacksAndMessages(null);
        if (dbHelper != null) {
            dbHelper.close();
        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mapView != null) {
            mapView.onSaveInstanceState(outState);
        }
    }

    private void showNavigationMenu() {
        PopupMenu popup = new PopupMenu(requireActivity(), binding.btnMenu);
        popup.getMenuInflater().inflate(R.menu.navigation_menu, popup.getMenu());

        popup.setOnMenuItemClickListener(item -> {
            int itemId = item.getItemId();
            if (itemId == R.id.menu_profile) {
                // 打开个人资料页面
                startActivity(new Intent(requireActivity(), ProfileActivity.class));
                return true;
            } else if (itemId == R.id.menu_settings) {
                // 打开设置页面
                startActivity(new Intent(requireActivity(), SettingsActivity.class));
                return true;
            } else if (itemId == R.id.menu_logout) {
                // 退出登录
                logout();
                return true;
            }
            return false;
        });

        popup.show();
    }

    private void logout() {
        CommonDialog commonDialog = new CommonDialog(getActivity()).atShow();
        commonDialog.getMainView().tips.
                setText(io.openim.android.ouicore.R.string.quit_tips);
        commonDialog.getMainView().cancel.setOnClickListener(v2 -> commonDialog.dismiss());
        commonDialog.getMainView().confirm.setOnClickListener(v2 -> {
            commonDialog.dismiss();
            WaitDialog waitDialog = new WaitDialog(getActivity());
            waitDialog.show();
            OpenIMClient.getInstance().logout(new OnBase<String>() {
                @Override
                public void onError(int code, String error) {
                    waitDialog.dismiss();
//                    if(dev) Toast(error + code);
                }

                @Override
                public void onSuccess(String data) {
                    waitDialog.dismiss();
                    IMUtil.logout((AppCompatActivity) getActivity(), LoginActivity.class);
                }
            });

        });
    }

    private void checkNetworkStatus() {
        ConnectivityManager cm = (ConnectivityManager) requireActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        isNetworkAvailable = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        if(dev) Toast.makeText(requireActivity(), "检查网络状况" + isNetworkAvailable, Toast.LENGTH_SHORT).show();

    }

    private void updateLocation(double latitude, double longitude) {
        checkNetworkStatus();
        if(dev) Toast.makeText(requireActivity(), "尝试上传定位" , Toast.LENGTH_SHORT).show();
        if (isNetworkAvailable) {
            checkNetworkStatus();
            // 尝试直接上传位置
//            if(dev) Toast.makeText(requireActivity(), "网络上传" , Toast.LENGTH_SHORT).show();
            uploadLocation(latitude, longitude);
        } else {
            checkNetworkStatus();
            // 网络不可用时保存到本地数据库
            if(dev) Toast.makeText(requireActivity(), "离线上传" , Toast.LENGTH_SHORT).show();
            saveLocationToDB(latitude, longitude);
        }
    }

    private void uploadLocation(double latitude, double longitude) {
        try {

            JSONObject requestBody = new JSONObject();
            requestBody.put("userId", currentUser.getId());
            requestBody.put("latitude", latitude);
            requestBody.put("longitude", longitude);

            Log.i(TAG, "currentUser: "+currentUser.getId());
            RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestBody.toString());
            okhttp3.Request request = new okhttp3.Request.Builder()
                    .url(API_UPDATE_LOCATION)
                    .addHeader("Authorization", "Bearer " + requireActivity().getSharedPreferences("user_info", MODE_PRIVATE).getString("token", ""))
                    .put(body)
                    .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                    // 上传失败时保存到本地数据库
                    saveLocationToDB(latitude, longitude);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        String responseData = response.body().string();
                        JSONObject jsonResponse = new JSONObject(responseData);
                        Log.d(TAG, "onResponse: \n"+ jsonResponse.toString());
                        if (jsonResponse.getInt("code") == 0) {
                            Log.d(TAG, "位置更新成功");
                        } else {
                            // API返回错误时也保存到本地数据库
                            saveLocationToDB(latitude, longitude);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        saveLocationToDB(latitude, longitude);
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            saveLocationToDB(latitude, longitude);
        }
    }

    private void saveLocationToDB(double latitude, double longitude) {
        LocationPoint point = new LocationPoint(
                0, // id由数据库自动生成
                currentUser.getId(),
                latitude,
                longitude,
                System.currentTimeMillis()
        );
        dbHelper.addLocation(point);
        Log.d(TAG, "位置已保存到本地数据库");
    }

    private void syncOfflineLocations() {
        if (!isNetworkAvailable) return;

        List<LocationPoint> unsyncedLocations = dbHelper.getUnsyncedLocations();
        if (unsyncedLocations.isEmpty()) return;

        try {
            JSONArray locationsArray = new JSONArray();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());

            for (LocationPoint point : unsyncedLocations) {
                JSONObject location = new JSONObject();
                location.put("userId", point.getUserId());
                location.put("latitude", point.getLatitude());
                location.put("longitude", point.getLongitude());
                location.put("createTime", sdf.format(new Date(point.getCreateTime())));
                locationsArray.put(location);
            }

            JSONObject requestBody = new JSONObject();
            requestBody.put("locations", locationsArray);

            RequestBody body = RequestBody.create(JSON, requestBody.toString());
            okhttp3.Request request = new okhttp3.Request.Builder()
                    .url(API_BATCH_UPDATE_LOCATION)
//                    .addHeader("Authorization", "Bearer " + getToken())
                    .post(body)
                    .build();

            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.e(TAG, "批量上传失败: " + e.getMessage());
                    if(dev) Toast.makeText(requireActivity(), "批量上传失败" + e.getMessage(), Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        for (LocationPoint point : unsyncedLocations) {
                            dbHelper.markLocationAsSynced(point.getId());
                        }
                        Log.d(TAG, "离线位置同步成功");
                        if(dev) Toast.makeText(requireActivity(), "离线位置同步成功", Toast.LENGTH_SHORT).show();
                    }
                }
            });
        } catch (Exception e) {
            Log.e(TAG, "构造请求失败: " + e.getMessage());
            if(dev) Toast.makeText(requireActivity(), "构造请求失败"+ e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }

    // 在MapFragment中添加
    private BroadcastReceiver networkReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            checkNetworkStatus();
            if (isNetworkAvailable) {
                syncOfflineLocations();
            }
        }
    };




}
